package com.sxt.config;

import java.time.LocalDateTime;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.sxt.entity.User;
import com.sxt.service.UserService;
import com.sxt.utils.IpUtils;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;


@Configuration
public class UserRealm extends AuthorizingRealm{


	@Autowired
	private UserService userService;

	@Autowired
	private RestTemplate restTemplate ;

	private static final String LOGIN_WECHAT_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";

	@Value("${wechat.appid}")
	private String appId;

	@Value("${wechat.secret}")
	private String secret ;
	/**
	 * 做授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		return null;
	}

	/**
	 * 做登录 subject.login(token)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken userNamePassToken = (UsernamePasswordToken) token;
		String code = userNamePassToken.getUsername();//username 是前端给我们传的code
		// 现在可以访问微信服务器获取openId
		//		String.format: 将%s 替换为 后面的值 
		//		String result = restTemplate.getForObject(String.format(LOGIN_WECHAT_URL, appId,secret,code), String.class); // 将json字符串无法转化为Hutool的JSONObject
		//restTemplate 底层会使用 jackson将json 转化为对象
		//->文本类型必须为application/json-> json->object 1 new 该对象(必须有构造器)  2 进行对象的属性注入(field.set(obj,value),使用setter)
		// 无法转化 为对象的原因时,响应头不是application/json, jackson 不能转化
		String result = restTemplate.getForObject(String.format(LOGIN_WECHAT_URL, appId,secret,code), String.class);
		// openId 获取到了 user的唯一标识,使用user_id 查询user表里面是否存在该用户
		//{"session_key":"Yui4`XbJdltXVYPZkJ1C2qg==","openid":"ovY9c1A0u8bJ5eMgLbVedeAJ1Zp8"}
		//appid 无效 ,就是你在微信小程序里面的appi 和 在yml 文件配置的appi 是否一样 ,以yml里面为主

		JSONObject jsonObject = JSONUtil.parseObj(result);
		String openId = null ;
		if(jsonObject.containsKey("openid")) {
			openId = jsonObject.getStr("openid");
		}else {
			throw new AuthenticationException("前检查你的appid 或者验证码是否过期");
		}

		User user = userService.findUserByUsername(openId); // Username : 是一个用户的 唯一标识
		if(user==null) { // 是用户第一次访问小程序
			user = buliderNewUser(openId);
			userService.save(user); // 它的user_id 无法到数据库里面,因为在sql 语句里面没有包含
			                //INSERT(sex,pic,nickName) values(?,?,?..) 原因在于没有把user_id 放进去,这是mp的bug
		}else {
			// 存在该用户
			updateUser(user);
			userService.updateById(user);
		}
		return new SimpleAuthenticationInfo(user, "WX", openId);
	}

	/**
	 * 若用户存在,则修改user的登录时间和地址
	 * @param user
	 */
	private void updateUser(User user) {
		user.setModifyTime(LocalDateTime.now());
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = requestAttributes.getRequest();
		String ipAddr = IpUtils.getIpAddr(request);
		user.setUserLastip(ipAddr);
		user.setUserLasttime(LocalDateTime.now());
	}

	private User buliderNewUser(String openId) {
		User user = new User();
		user.setUserId(openId) ;//userid = openId 他是唯一的
		user.setModifyTime(LocalDateTime.now());
		user.setUserRegtime(LocalDateTime.now());
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = requestAttributes.getRequest();
		String ipAddr = IpUtils.getIpAddr(request);
		user.setUserRegip(ipAddr);
		user.setUserLastip(ipAddr);
		user.setUserLasttime(LocalDateTime.now());
		user.setStatus(1);
		return user;
	}

}
